﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using WeDonekRpc.Helper;
using WeDonekRpc.IOBuffer;
using WeDonekRpc.PipeServer.Config;
using WeDonekRpc.PipeServer.Interface;
using WeDonekRpc.PipeServer.Server;
using WeDonekRpc.PipeServer.SystemAllot;

namespace WeDonekRpc.PipeServer
{
    public class PipeServer
    {
        private static readonly Timer _CheckTimer;
        static PipeServer ()
        {
            BufferCollect.InitBuffer();
            _CheckTimer = new Timer(new TimerCallback(_CheckIsCon), null, 60000, 60000);
        }
        private static void _CheckIsCon (object state)
        {
            PipeServer.CheckClientIsCon();
        }


        private static readonly Dictionary<string, ServerInfo> serverList = [];

        public static string DefaultPipeName => Config.PipeConfig.DefaultPipeName;

        private static void InitServer ()
        {
            IAllot allot = Config.PipeConfig.DefaultAllot;
            if (allot == null)
            {
                allot = new UserAllotInfo();
            }
            AddServer(Config.PipeConfig.DefaultPipeName, allot);
        }


        /// <summary>
        /// 注册一个新的管道服务
        /// </summary>
        /// <param name="port"></param>
        public static void AddServer (string pipeName, Interface.IAllot allot)
        {
            if (allot == null)
            {
                throw new ErrorException("ipc.allot.null");
            }
            else if (serverList.ContainsKey(pipeName))
            {
                throw new ErrorException("ipc.pipe.name.repeat");
            }
            Server.ServerInfo objServer = new ServerInfo(pipeName, allot, Config.PipeConfig.PipeEvent, Config.PipeConfig.ServerKey);
            serverList.Add(pipeName, objServer);
            objServer.InitServer();
        }
        public static void AddServer (string pipeName, Interface.IAllot allot, IPipeEvent socketEvent)
        {
            AddServer(pipeName, allot, socketEvent, Config.PipeConfig.ServerKey);
        }
        /// <summary>
        /// 注册一个新的Socket服务
        /// </summary>
        /// <param name="port"></param>
        public static void AddServer (string pipeName, IAllot allot, IPipeEvent socketEvent, string punlicKey)
        {
            if (allot == null)
            {
                throw new ErrorException("ipc.allot.null");
            }
            else if (serverList.ContainsKey(pipeName))
            {
                throw new ErrorException("ipc.pipe.name.repeat");
            }
            punlicKey = Tools.GetMD5(punlicKey);
            Server.ServerInfo objServer = new Server.ServerInfo(pipeName, allot, socketEvent, punlicKey);
            serverList.Add(pipeName, objServer);
            objServer.InitServer();
        }
        public static int GetSocketClientNum (string pipeName)
        {
            if (serverList.ContainsKey(pipeName))
            {
                return serverList[pipeName].ClientCount;
            }
            return 0;
        }

        internal static bool CheckPublicKey (string pipeName, string key)
        {
            if (serverList.TryGetValue(pipeName, out Server.ServerInfo server))
            {
                return server.PublicKey == key;
            }
            return false;
        }

        public static void CloseClient (params Guid[] clientId)
        {
            if (clientId != null)
            {
                CloseClient(PipeConfig.DefaultPipeName, clientId);
            }
        }
        public static void CloseClient (string pipeName, params Guid[] clientId)
        {
            if (clientId != null)
            {
                if (serverList.TryGetValue(pipeName, out ServerInfo server))
                {
                    foreach (Guid i in clientId)
                    {
                        server.CloseClient(i);
                    }
                }
            }
        }

        /// <summary>
        /// 客户端关闭事件
        /// </summary>
        /// <param name="clientId"></param>
        internal static void ClientCloseEvent (string pipeName, Guid clientId)
        {
            if (serverList.TryGetValue(pipeName, out ServerInfo server))
            {
                server.ClientCloseEvent(clientId);
            }
        }

        internal static void CloseClient (string pipeName, Guid clientId)
        {
            if (serverList.TryGetValue(pipeName, out ServerInfo server))
            {
                server.CloseClient(clientId);
            }
        }

        public static void CloseServer ()
        {
            foreach (Server.ServerInfo i in serverList.Values)
            {
                i.CloseServer();
            }
            LogSystem.CloseLog();
        }

        public static void CloseServer (string pipeName)
        {
            Server.ServerInfo server = serverList.Values.Where(a => a.PipeName == pipeName).FirstOrDefault();
            server?.CloseServer();
        }

        internal static void CheckClientIsCon ()
        {
            foreach (ServerInfo i in serverList.Values)
            {
                i.CheckIsCon();
            }
        }



        internal static bool GetServer (string pipeName, out ServerInfo server)
        {
            return serverList.TryGetValue(pipeName, out server);
        }
        internal static bool GetServer (string pipeName, out ServerInfo server, out string error)
        {
            if (!serverList.TryGetValue(pipeName, out server))
            {
                error = "pipe.server.not.find";
                return false;
            }
            error = null;
            return true;
        }
        public static void Init ()
        {
            InitServer();
        }
    }
}
